package com.decheng.java8.lambda;

import com.decheng.java8.entity.Employee;
import com.decheng.java8.entity.EmployeeData;
import org.junit.Test;

import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 方法引用的使用
 * 1. 什么时候用？当要传递给 Lambda 体的操作，已经有实现的方法时，可以使用方法引用
 * 2. 怎么用？类(或对象) :: 方法名
 * 2.1 对象 :: 非静态方法
 * 2.2 类 :: 静态方法
 * 2.3 类 :: 非静态方法
 * 3. 使用技巧：要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同！（针对于情况1和情况2）
 *
 * @author codemao
 */
public class MethodRefTest {

    // 情况一：对象 :: 实例方法
    // Consumer 中的 void accept(T t)
    // PrintStream 中的 void println(T t)
    @Test
    public void test1() {
        Consumer<String> consumer = s -> System.out.println(s);
        consumer.accept("Hello,World!");
        System.out.println("----------------------------------------✂----------------------------------------");
        Consumer<String> consumer1 = System.out::println;
        consumer1.accept("Hello,World!");

    }

    // Supplier 中的 T get()
    // Employee 中的 String getName()
    @Test
    public void test2() {
        Employee employee = EmployeeData.getEmployees().get(0);
        Supplier<String> supplier = () -> employee.getName();
        String s = supplier.get();
        System.out.println("s = " + s);
        System.out.println("----------------------------------------✂----------------------------------------");
        Supplier<String> supplier1 = employee::getName;
        String s1 = supplier1.get();
        System.out.println("s1 = " + s1);


    }

    // 情况二：类 :: 静态方法
    // Comparator 中的 int compare(T t1,T t2)
    // Integer 中的 int compare(T t1,T t2)
    @Test
    public void test3() {
        Comparator<Integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
        int compare = comparator.compare(1, 2);
        System.out.println("compare = " + compare);
        System.out.println("----------------------------------------✂----------------------------------------");
        Comparator<Integer> comparator1 = Integer::compare;
        int compare1 = comparator1.compare(1, 2);
        System.out.println("compare1 = " + compare1);
    }

    // Function 中的 R apply(T t)
    // Math 中的 Long round(Double d)
    @Test
    public void test4() {
        Function<Double, Long> function = d -> Math.round(d);
        Long apply = function.apply(5.675);
        System.out.println("apply = " + apply);
        System.out.println("----------------------------------------✂----------------------------------------");
        Function<Double, Long> function1 = Math::round;
        Long apply1 = function1.apply(5.675);
        System.out.println("apply1 = " + apply1);

    }

    // 情况三：类 :: 实例方法
    // Comparator 中的 int comapre(T t1,T t2)
    // String中 的 int t1.compareTo(t2)
    @Test
    public void test5() {
        Comparator<Integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
        int compare = comparator.compare(1, 2);
        System.out.println("compare = " + compare);
        System.out.println("----------------------------------------✂----------------------------------------");
        Comparator<Integer> comparator1 = Integer::compareTo;
        int compare1 = comparator1.compare(1, 2);
        System.out.println("compare1 = " + compare1);
    }

    // BiPredicate 中的 boolean test(T t1, T t2);
    // String 中的 boolean t1.equals(t2)
    @Test
    public void test6() {
        BiPredicate<String, String> biPredicate = (s1, s2) -> s1.equals(s2);
        boolean test = biPredicate.test("aa", "bb");
        System.out.println("test = " + test);
        System.out.println("----------------------------------------✂----------------------------------------");
        BiPredicate<String, String> biPredicate1 = String::equals;
        boolean test1 = biPredicate1.test("aa", "aa");
        System.out.println("test1 = " + test1);
    }

    // Function 中的 R apply(T t)
    // Employee 中的 String getName();
    @Test
    public void test7() {
        Employee e = EmployeeData.getEmployees().get(0);
        Function<Employee, String> function = employee -> employee.getName();
        String apply = function.apply(e);
        System.out.println("apply = " + apply);
        System.out.println("----------------------------------------✂----------------------------------------");
        Function<Employee, String> function1 = Employee::getName;
        String apply1 = function1.apply(e);
        System.out.println("apply1 = " + apply1);

    }

}
